home *** CD-ROM | disk | FTP | other *** search
- (*----------------------------------------------------------------------*)
- (* Async_Send --- Send character over communications port *)
- (*----------------------------------------------------------------------*)
-
- PROCEDURE Async_Send( C : Char );
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Procedure: Async_Send *)
- (* *)
- (* Purpose: Sends character out over communications port *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Async_Send( C : Char ); *)
- (* *)
- (* C --- Character to send *)
- (* *)
- (* Calls: None *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- BEGIN (* Async_Send *)
-
- INLINE(
- $8A/$46/<C { MOV AL,[BP+<C] ;Pick up character to send}
- /$8B/$1E/>ASYNC_OBUFFER_HEAD { MOV BX,[>Async_OBuffer_Head] ;Get output queue head pointer}
- /$C4/$3E/>ASYNC_OBUFFER_PTR { LES DI,[>Async_OBuffer_Ptr] ;Pick up output buffer address}
- /$01/$DF { ADD DI,BX ;Position to current character}
- /$26/$88/$05 { ES: MOV [DI],AL ;Place character in output buffer}
- {;}
- /$89/$DA { MOV DX,BX ;Save previous head pointer}
- /$43 { INC BX ;Increment head pointer}
- /$3B/$1E/>ASYNC_OBUFFER_SIZE { CMP BX,[>Async_OBuffer_Size] ;See if past end of buffer}
- /$7E/$02 { JLE Send1 ;Skip if not}
- /$31/$DB { XOR BX,BX ;Wrap to start of buffer}
- {;}
- /$3B/$1E/>ASYNC_OBUFFER_TAIL {Send1: CMP BX,[>Async_OBuffer_Tail] ;See if head collided with tail}
- /$75/$1C { JNE Send4 ;No -- buffer didn't fill up}
- {;}
- /$8B/$0E/>ASYNC_OUTPUT_DELAY { MOV CX,[>Async_Output_Delay] ;Run delay loop and see if buffer drains}
- {;}
- /$51 {Send2: PUSH CX ;Save milleseconds to go}
- /$8B/$0E/$12/$00 { MOV CX,[$12] ;Get Turbo's delay loop value for 1 ms}
- {;}
- /$E2/$FE {Send3: LOOP Send3 ;Tight loop for 1 ms delay}
- {;}
- /$3B/$1E/>ASYNC_BUFFER_TAIL { CMP BX,[>Async_Buffer_Tail] ;See if buffer drained yet}
- /$75/$0B { JNE Send4 ;Yes -- OK, stop delay loop.}
- {;}
- /$59 { POP CX ;Otherwise, get millesecond count}
- /$E2/$F0 { LOOP Send2 ;Decrement millesecond count and loop}
- {;}
- /$C6/$06/>ASYNC_OBUFFER_OVERFLOW/$01{ MOV BYTE [>Async_OBuffer_Overflow],1 ;Indicate output buffer overflow}
- /$E9/$14/$00 { JMP Send5 ;Skip updating head pointers}
- {;}
- /$89/$1E/>ASYNC_OBUFFER_HEAD {Send4: MOV [>Async_OBuffer_Head],BX ;Save updated head pointer}
- {;}
- /$A1/>ASYNC_OBUFFER_USED { MOV AX,[>Async_OBuffer_Used] ;Get buffer use count}
- /$40 { INC AX ;Increment buffer use count}
- /$A3/>ASYNC_OBUFFER_USED { MOV [>Async_OBuffer_Used],AX ;Save new count}
- /$3B/$06/>ASYNC_MAXOBUFFERUSED { CMP AX,[>Async_MaxOBufferUsed] ;See if larger than ever before}
- /$7E/$03 { JLE Send5 ;Skip if not}
- /$A3/>ASYNC_MAXOBUFFERUSED { MOV [>Async_MaxOBufferUsed],AX ;Save new maximum usage}
- {;}
- /$8B/$16/>ASYNC_UART_IER {Send5: MOV DX,[>Async_Uart_IER] ;Get interrupt enable register}
- /$EC { IN AL,DX ;Check contents of IER}
- /$A8/$02 { TEST AL,2 ;See if write interrupt enabled}
- /$75/$03 { JNZ Send6 ;Skip if so}
- /$0C/$02 { OR AL,2 ;Else enable write interrupts ...}
- /$EE { OUT DX,AL ;... by rewriting IER contents}
- {;}
- {Send6:}
- );
-
- END (* Async_Send *);
-
- (*----------------------------------------------------------------------*)
- (* Async_Receive --- Return character from buffer *)
- (*----------------------------------------------------------------------*)
-
- FUNCTION Async_Receive( VAR C : Char ) : BOOLEAN;
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Function: Async_Receive *)
- (* *)
- (* Purpose: Retrieve character (if any) from buffer *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Flag := Async_Receive( VAR C: Char ) : BOOLEAN; *)
- (* *)
- (* C --- character (if any) retrieved from buffer; *)
- (* set to CHR(0) if no character available. *)
- (* *)
- (* Flag returned TRUE if character retrieved from buffer, *)
- (* Flag returned FALSE if no character retrieved. *)
- (* *)
- (* Calls: None *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- BEGIN (* Async_Receive *)
-
- INLINE(
- {;}
- {; Check if any characters in input comm buffer}
- {;}
- $A1/>ASYNC_BUFFER_TAIL { MOV AX,[>Async_Buffer_Tail]}
- /$3B/$06/>ASYNC_BUFFER_HEAD { CMP AX,[>Async_Buffer_Head]}
- /$75/$0B { JNE Rec1}
- {;}
- {; Buffer is empty -- return NUL character}
- {;}
- /$C4/$7E/<C { LES DI,[BP+<C] ;Get character address}
- /$31/$C0 { XOR AX,AX ;Clear out unused bits}
- /$26/$88/$05 { ES: MOV [DI],AL ;NUL character}
- /$E9/$41/$00 { JMP Return}
- {;}
- {; Buffer not empty -- pick up next character.}
- {;}
- /$C4/$3E/>ASYNC_BUFFER_PTR {Rec1: LES DI,[>Async_Buffer_Ptr] ;Pick up buffer address}
- /$01/$C7 { ADD DI,AX ;Add character offset}
- /$26/$8A/$1D { ES: MOV BL,[DI] ;Get character from buffer}
- /$C4/$7E/<C { LES DI,[BP+<C] ;Get result address}
- /$26/$88/$1D { ES: MOV [DI],BL ;Store character from buffer}
- /$40 { INC AX ;Increment tail pointer}
- /$3B/$06/>ASYNC_BUFFER_SIZE { CMP AX,[>Async_Buffer_Size] ;Past end of buffer?}
- /$7E/$02 { JLE Rec2 ;No -- skip wrapping}
- /$31/$C0 { XOR AX,AX ;Yes -- point to start of buffer}
- /$A3/>ASYNC_BUFFER_TAIL {Rec2: MOV [>Async_Buffer_Tail],AX ;Update tail pointer}
- /$FF/$0E/>ASYNC_BUFFER_USED { DEC Word [>Async_Buffer_Used] ;Update buffer use count}
- {;}
- {; If XOFF previously sent because buffer was too full, and}
- {; now buffer is reasonably empty, send XON to get things rolling again.}
- {;}
- /$F6/$06/>ASYNC_XOFF_SENT/$01 { TEST BYTE [<Async_XOff_Sent],1 ;Check if Xoff sent}
- /$74/$18 { JZ Rec3 ;No -- skip.}
- {;}
- /$A1/>ASYNC_BUFFER_USED { MOV AX,[>Async_Buffer_Used] ;Pick up amount of buffer used}
- /$3B/$06/>ASYNC_BUFFER_LOW { CMP AX,[>Async_Buffer_Low] ;Check if low enough}
- /$7F/$0F { JG Rec3 ;Still too full, skip}
- {;}
- /$B8/>XON { MOV AX,>XON ;Else push XON onto stack}
- /$50 { PUSH AX}
- /$8D/$1E/>ASYNC_SEND { LEA BX,[>Async_Send] ;Call output routine}
- {;}
- {;-----WARNING---- Following statement must be fixed by hand in .OBJ file!}
- {;---------------- Generated code should read:}
- {; $FF/ $D3/}
- {;}
- /$FF/$D3 { CALL [BX] ;THIS MUST BE FIXED BY HAND!!!!!}
- {;}
- /$C6/$06/>ASYNC_XOFF_SENT/$00 { MOV BYTE [>Async_XOff_Sent],0 ;Clear Xoff flag}
- {;}
- {; Indicate character found}
- {;}
- /$B8/$01/$00 {Rec3: MOV AX,1}
- {;}
- /$80/$26/>ASYNC_LINE_STATUS/$FD{Return: AND Byte [>Async_Line_Status],$FD ;Remove overflow flag}
- /$09/$C0 { OR AX,AX ;Set zero flag to indicate return status}
- /$89/$EC { MOV SP,BP}
- /$5D { POP BP}
- /$C2/$05/$00 { RET 5}
- );
-
- END (* Async_Receive *);
-
- (*----------------------------------------------------------------------*)
- (* Async_Receive_With_TimeOut --- Return char. from buffer with delay *)
- (*----------------------------------------------------------------------*)
-
- PROCEDURE Async_Receive_With_Timeout( Secs : INTEGER; VAR C : INTEGER );
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Procedure: Async_Receive_With_Timeout *)
- (* *)
- (* Purpose: Retrieve character as integer from buffer, *)
- (* or return TimeOut if specified delay period *)
- (* expires. *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Async_Receive_With_Timeout( Secs: INTEGER; VAR C: INTEGER ); *)
- (* *)
- (* Secs --- Timeout period in seconds *)
- (* NOTE: Cannot be longer than 32 seconds! *)
- (* C --- ORD(character) (if any) retrieved from buffer; *)
- (* set to TimeOut if no character found before *)
- (* delay period expires. *)
- (* *)
- (* Calls: Async_Receive *)
- (* TimeOfDay *)
- (* *)
- (* WATCH OUT! THIS ROUTINE RETURNS AN INTEGER, NOT A CHARACTER!!! *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- BEGIN (* Async_Receive_With_Timeout *)
-
- INLINE(
- {;}
- {; Check if a character in input comm buffer}
- {;}
- $A1/>ASYNC_BUFFER_TAIL { MOV AX,[>Async_Buffer_Tail]}
- /$3B/$06/>ASYNC_BUFFER_HEAD { CMP AX,[>Async_Buffer_Head]}
- /$75/$29 { JNE Rec1}
- {;}
- {; Buffer empty -- begin wait loop.}
- {;}
- /$8B/$46/<SECS { MOV AX,[BP+<Secs] ;Get seconds to wait}
- /$B9/$0A/$00 { MOV CX,10 ;Shift count = 2 ** 10 = 1024}
- /$D3/$E0 { SHL AX,CL ;Seconds * 1024 = milleseconds}
- /$89/$C1 { MOV CX,AX ;Move to looping register}
- {;}
- {; Delay for 1 ms.}
- {;}
- /$51 {Delay: PUSH CX ;Save milleseconds to go}
- /$8B/$0E/$12/$00 { MOV CX,[$12] ;Get Turbo's delay loop value for 1 ms}
- /$E2/$FE {Delay1: LOOP Delay1 ;Tight loop for 1 ms delay}
- {;}
- {; Check if any character yet.}
- {;}
- /$A1/>ASYNC_BUFFER_TAIL { MOV AX,[>Async_Buffer_Tail]}
- /$3B/$06/>ASYNC_BUFFER_HEAD { CMP AX,[>Async_Buffer_Head]}
- /$75/$0F { JNE Rec1}
- {;}
- {; Buffer still empty -- decrement elapsed time}
- {;}
- /$59 { POP CX ;Get millesecond count}
- /$E2/$ED { LOOP Delay ;Decrement millesecond count and loop}
- {;}
- {; Dropped through -- no character arrived in specified interval.}
- {; Return TimeOut as result.}
- {;}
- /$BB/>TIMEOUT { MOV BX,>TimeOut ;Pick up timeout value}
- /$C4/$7E/<C { LES DI,[BP+<C] ;Get result character address}
- /$26/$89/$1D { ES: MOV [DI],BX ;Store timeout value}
- /$E9/$40/$00 { JMP Return ;Return to caller}
- {;}
- {; Buffer not empty -- pick up next character.}
- {;}
- /$C4/$3E/>ASYNC_BUFFER_PTR {Rec1: LES DI,[>Async_Buffer_Ptr] ;Pick up buffer address}
- /$01/$C7 { ADD DI,AX ;Add character offset}
- /$26/$8A/$1D { ES: MOV BL,[DI] ;Get character from buffer}
- {;}
- /$30/$FF { XOR BH,BH ;Clear high-order bits}
- /$C4/$7E/<C { LES DI,[BP+<C] ;Get result address}
- /$26/$89/$1D { ES: MOV [DI],BX ;Store character from buffer}
- {;}
- /$40 { INC AX ;Increment tail pointer}
- /$3B/$06/>ASYNC_BUFFER_SIZE { CMP AX,[>Async_Buffer_Size] ;Past end of buffer?}
- /$7E/$02 { JLE Rec2 ;No -- skip wrapping}
- /$31/$C0 { XOR AX,AX ;Yes -- point to start of buffer}
- /$A3/>ASYNC_BUFFER_TAIL {Rec2: MOV [>Async_Buffer_Tail],AX ;Update tail pointer}
- /$FF/$0E/>ASYNC_BUFFER_USED { DEC Word [>Async_Buffer_Used] ;Update buffer usage count}
- {;}
- {; If XOFF previously sent because buffer was too full, and}
- {; now buffer is reasonably empty, send XON to get things rolling again.}
- {;}
- /$F6/$06/>ASYNC_XOFF_SENT/$01 { TEST BYTE [<Async_XOff_Sent],1 ;Check if Xoff sent}
- /$74/$18 { JZ Return ;No -- skip.}
- {;}
- /$A1/>ASYNC_BUFFER_USED { MOV AX,[>Async_Buffer_Used] ;Pick up amount of buffer used}
- /$3B/$06/>ASYNC_BUFFER_LOW { CMP AX,[>Async_Buffer_Low] ;Check if low enough}
- /$7F/$0F { JG Return ;Still too full, skip}
- {;}
- /$B8/>XON { MOV AX,>XON ;Push XON onto stack}
- /$50 { PUSH AX}
- /$8D/$1E/>ASYNC_SEND { LEA BX,[>Async_Send] ;Call output routine}
- {;}
- {;-----WARNING---- Following statement must be fixed by hand in .OBJ file!}
- {;---------------- Generated code should read:}
- {; $FF/ $D3/}
- {;}
- /$FF/$D3 { CALL [BX] ;THIS MUST BE FIXED BY HAND!!!!!}
- {;}
- /$C6/$06/>ASYNC_XOFF_SENT/$00 { MOV BYTE [>Async_XOff_Sent],0 ;Clear Xoff flag}
- {;}
- /$80/$26/>ASYNC_LINE_STATUS/$FD{Return: AND Byte [>Async_Line_Status],$FD ;Remove overflow flag}
- );
-
- END (* Async_Receive_With_Timeout *);
-
- (*----------------------------------------------------------------------*)
- (* Async_Stuff --- Stuff character into receive buffer *)
- (*----------------------------------------------------------------------*)
-
- PROCEDURE Async_Stuff( Ch: CHAR );
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Procedure: Async_Stuff *)
- (* *)
- (* Purpose: Stuffs a character into receive buffer *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Async_Stuff( Ch : Char ); *)
- (* *)
- (* Ch --- Character to stuff *)
- (* *)
- (* Calls: None *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- VAR
- New_Head : INTEGER;
-
- BEGIN (* Async_Stuff *)
-
- Async_Buffer_Ptr^[Async_Buffer_Head] := Ch;
- New_Head := Async_Buffer_Head + 1;
-
- IF ( New_Head > Async_Buffer_Size ) THEN
- New_Head := 0;
-
- IF ( New_Head = Async_Buffer_Tail ) THEN
- Async_Buffer_Overflow := TRUE
- ELSE
- BEGIN
- Async_Buffer_Head := New_Head;
- Async_Buffer_Used := Async_Buffer_Used + 1;
- IF ( Async_Buffer_Used > Async_MaxBufferUsed ) THEN
- Async_MaxBufferUsed := Async_Buffer_Used
- END;
-
- END (* Async_Stuff *);